﻿using System;
using System.Collections.Generic;
using System.Diagnostics;

public class Nextension
{
    /// <summary>
    /// Creates a list by applying a function to the last item in the list to generate the next item.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source">The first item in the list.</param>
    /// <param name="count">The number of items to return.</param>
    /// <param name="iterator">The delegate to generate the next item from.</param>
    /// <returns>A list of generated items.</returns>
    public static IEnumerable<T> Iterate<T>(T source, int count, Func<T, T> iterator)
    {
        if (source == null)
            throw new ArgumentNullException("source", "source is null.");
        if (iterator == null)
            throw new ArgumentNullException("iterator", "iterator is null.");

        return IterateIterator<T>(source, count, iterator);
    }

    private static IEnumerable<T> IterateIterator<T>(T source, int count, Func<T, T> iterator)
    {
        Debug.Assert(source != null, "source is null.");
        Debug.Assert(iterator != null, "iterator is null.");

        int i = 0;
        T result = source;
        while (i < count)
        {
            yield return result;
            result = iterator(result);
            i++;
        }
    }

    /// <summary>
    /// Creates a list of items by repeating the same item.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source">The item to repeat.</param>
    /// <param name="count">The number of items to return.</param>
    /// <returns>A list of items repeated.</returns>
    public static IEnumerable<T> Repeat<T>(T source, int count)
    {
        if (source == null)
            throw new ArgumentNullException("source", "source is null.");

        return RepeatIterator<T>(source, count);
    }

    private static IEnumerable<T> RepeatIterator<T>(T source, int count)
    {
        Debug.Assert(source != null, "source is null.");

        int i = 0;
        while (i < count)
        {
            yield return source;
            i++;
        }
    }

}
